const dbHelper = require('./utils/dbHelper')
const randomHelper = require('./utils/randomHelper')
const { doControl } = require('./control')
const runtimeLogger = require('../log4js')()

module.exports = class Service {
  constructor({ header, payload }) {
    runtimeLogger.info(`构造Service实例, header: ${JSON.stringify(header)}, payload: ${JSON.stringify(payload)}`)
    const { namespace, thirdPartyId, granteeId, messageId, timestamp } = header
    this.namespace = namespace
    this.granteeId = granteeId
    this.thirdPartyId = thirdPartyId
    this.header = header
    this.payload = payload
    this.baseRPayload = {
      code: 0,
      description: 'success'
    }
  }

  /**
   * 根据namespace执行对应的function
   */
  run() {
    // AcceptGrant => acceptGrant
    return Promise.resolve(this[this.namespace.replace(/^[A-Z]/, c => c.toLowerCase())]())
  }

  /**
   * 账号授权
   */
  async acceptGrant() {
    const grantedDev = await this.isGranted()
    // 支持重复授权
    if (grantedDev) {
      runtimeLogger.info(`该用户granteeId:${this.granteeId} 已经在车厂 thirdPartyId: ${this.thirdPartyId} 授权过`)
      return {
        header: Object.assign({}, this.header, { timestamp: Date.now() }),
        payload: Object.assign({}, this.baseRPayload, { thirdPartyUserId: grantedDev.thirdPartyUserId })
      }
    }
    const thirdPartyUserId = randomHelper.thirdPartyUserId()

    // 如果在该用户名下没有车则根据车厂补偿一辆车辆
    await dbHelper.insertDev({
      thirdPartyId: this.thirdPartyId,
      thirdPartyUserId,
      status: 'online',
      granteeId: this.granteeId
    })

    runtimeLogger.info(`在车厂 thirdPartyId: ${this.thirdPartyId} 授权 granteeId:${this.granteeId} 成功, 分配 thirdPartyUserId: ${thirdPartyUserId}`)

    return {
      header: Object.assign({}, this.header, { timestamp: Date.now() }),
      payload: Object.assign({}, this.baseRPayload, { thirdPartyUserId })
    }
  }

  /**
   * 取消授权
   *    删除之前的授权信息
   */
  async cancelGrant() {
    runtimeLogger.info(`取消用户 granteeId:${this.granteeId} 在车厂 thirdPartyId: ${this.thirdPartyId} 的授权信息`)
    await dbHelper.T_DEVICES.delete(`thirdPartyId = '${this.thirdPartyId}' AND granteeId = '${this.granteeId}'`)
    return {
      header: Object.assign({}, this.header, { timestamp: Date.now() }),
      payload: Object.assign({}, this.baseRPayload)
    }
  }

  /**
   * 设备发现
   */
  async deviceDiscovery() {
    // 暂不支持一个三方userId绑定多个华为uid的场景, 所以这里可以根据granteeId作为查询条件
    // 否则必须是从AT中解析出来的userId作为查询条件
    const devs = await dbHelper.queryDevs(`granteeId = "${this.granteeId}" AND thirdPartyId = "${this.thirdPartyId}"`)

    return {
      header: Object.assign({}, this.header, { timestamp: Date.now() }),
      payload: Object.assign({}, this.baseRPayload, {
        devices: await Promise.all((devs || []).map(async dev => {
          const { thirdPartyDevId, udid, prodId } = dev
          // 拿到prodId之后去tsps表查询, 然后组装services返回
          const tsps = await dbHelper.T_TSPS.query(`thirdPartyId = '${this.thirdPartyId}' AND prodId = '${prodId}'`)
          if (tsps && tsps.length <= 0) {
            runtimeLogger.info(`查询车厂 thirdPartyId: ${this.thirdPartyId} 的车型:${prodId} 失败`)
            throw new Error(`查询车厂 thirdPartyId: ${this.thirdPartyId} 的车型:${prodId} 失败`)
          }
          const { devName, services, model, devType, manu, hiv } = tsps[0]
          return {
            thirdPartyDevId,
            devName,
            devInfo: {
              udid, model, devType, manu, prodId, hiv
            },
            services: JSON.parse(services)
          }
        }))
      })
    }
  }

  /**
   * 设备快照
   */
  async deviceSnapshot() {
    const { thirdPartyDevIds } = this.payload
    const where = `granteeId = "${this.granteeId}" AND thirdPartyId = "${this.thirdPartyId}" AND thirdPartyDevId IN (${thirdPartyDevIds.map(t => `'${t}'`).join(',')})`
    const devs = await dbHelper.queryDevs(where)
    return {
      header: Object.assign({}, this.header, { timestamp: Date.now() }),
      payload: Object.assign({}, this.baseRPayload, (devs || []).map(dev => {
        const { thirdPartyDevId, serviceData, status } = dev
        return {
          thirdPartyDevId,
          status,
          services: JSON.parse(serviceData)
        }
      }))
    }
  }

  /**
   * 设备订阅
   */
  async subscribeDevice() {
    const { thirdPartyDevIds } = this.payload
    const where = `granteeId = '${this.granteeId}' AND thirdPartyId = '${this.thirdPartyId}' AND thirdPartyDevId IN (${thirdPartyDevIds.map(t => `'${t}'`).join(',')})`
    const devs = await dbHelper.queryDevs(where)
    return {
      header: Object.assign({}, this.header, { timestamp: Date.now() }),
      payload: Object.assign({}, this.baseRPayload, (devs || []).map(dev => {
        const { thirdPartyDevId, serviceData, status } = dev
        return {
          thirdPartyDevId,
          status,
          services: JSON.parse(serviceData)
        }
      }))
    }
  }

  unsubscribeDevice() {
    return {
      header: Object.assign({}, this.header, { timestamp: Date.now() }),
      payload: Object.assign({}, this.baseRPayload)
    }
  }

  async deviceCommand() {
    const { command } = this.payload
    const { code } = await doControl(command)

    return {
      header: Object.assign({}, this.header, { timestamp: Date.now() }),
      payload: Object.assign({}, this.baseRPayload, { code })
    }
  }

  /**
   * 判断当前用户是否已经授权过, 已经授权过返回已有的授权信息
   */
  async isGranted() {
    const devs = await dbHelper.T_DEVICES.query(`thirdPartyId = '${this.thirdPartyId}' AND granteeId = '${this.granteeId}'`)
    return devs && devs.length > 0 && devs[0]
  }
}
